package com.liam.translation.xunfei;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

/**
 * 讯飞机器翻译（新）API服务
 * 直接调用讯飞机器翻译（新）API，支持中英互译
 * 
 * @author liam
 */
public class NewTranslationService {

    private static final Logger logger = LoggerFactory.getLogger(NewTranslationService.class);

    // 讯飞机器翻译（新）API请求URL
    private static final String REQUEST_URL = "https://itrans.xf-yun.com/v1/its";

    // 讯飞翻译API鉴权参数
    private static final String APP_ID = "98e7934f";
    private static final String API_KEY = "17352bf789ecaa4e9483ff7a60ee76e2";
    private static final String API_SECRET = "ZDkxNDAwMmNjNjNhZTc1OWZiNDFiYzkz";

    // 术语资源唯一标识，如不需术语可以不传递此参数
    private static final String RES_ID = "";

    // 语言代码
    public static final String LANG_CHINESE = "cn";
    public static final String LANG_ENGLISH = "en";

    // 单例实例
    private static NewTranslationService instance;

    /**
     * 获取翻译服务实例（单例模式）
     * 
     * @return 翻译服务实例
     */
    public static synchronized NewTranslationService getInstance() {
        if (instance == null) {
            instance = new NewTranslationService();
        }
        return instance;
    }

    /**
     * 构造函数，初始化翻译服务
     */
    private NewTranslationService() {
        logger.info("讯飞机器翻译（新）API服务已初始化");
    }

    /**
     * 通用翻译方法，支持中英互译
     * 
     * @param text     要翻译的文本
     * @param fromLang 源语言代码（cn或en）
     * @param toLang   目标语言代码（cn或en）
     * @return 翻译后的文本
     */
    public String translate(String text, String fromLang, String toLang) {
        if (text == null || text.trim().isEmpty()) {
            return "";
        }

        try {
            // 调用讯飞机器翻译（新）API
            String response = doRequest(text, fromLang, toLang);
            logger.debug("翻译响应: {}", response);

            // 解析翻译结果
            JSONObject jsonResponse = JSON.parseObject(response);
            if (jsonResponse.containsKey("payload") && jsonResponse.getJSONObject("payload").containsKey("result")) {
                String textBase64 = jsonResponse.getJSONObject("payload").getJSONObject("result").getString("text");
                String textJson = new String(Base64.getDecoder().decode(textBase64), "UTF-8");

                // 打印完整的JSON响应，确认字段名
                logger.debug("解码后的翻译结果JSON: {}", textJson);

                // 解析JSON结果
                JSONObject resultJson = JSON.parseObject(textJson);

                // 首先检查是否有trans_result字段（可能包含src和dst）
                if (resultJson.containsKey("trans_result")) {
                    JSONObject transResult = resultJson.getJSONObject("trans_result");
                    if (transResult.containsKey("dst")) {
                        String translatedText = transResult.getString("dst");
                        logger.info("翻译成功 ({} -> {}): {} -> {}", fromLang, toLang, text, translatedText);
                        return translatedText;
                    }
                }

                // 如果trans_result不存在，直接查找dst字段
                if (resultJson.containsKey("dst")) {
                    String translatedText = resultJson.getString("dst");
                    logger.info("翻译成功 ({} -> {}): {} -> {}", fromLang, toLang, text, translatedText);
                    return translatedText;
                }

                // 如果dst不存在，查找src字段作为fallback（可能是反向翻译）
                if (resultJson.containsKey("src")) {
                    String translatedText = resultJson.getString("src");
                    logger.info("翻译成功 (使用src字段) ({} -> {}): {} -> {}", fromLang, toLang, text, translatedText);
                    return translatedText;
                }

                // 如果以上都没有，返回整个JSON以便调试
                logger.warn("未找到预期的翻译字段，返回完整JSON: {}", textJson);
                return textJson;
            } else {
                logger.warn("翻译响应格式异常: {}", response);
                return "翻译失败: 响应格式异常";
            }
        } catch (Exception e) {
            logger.error("翻译异常", e);
            return "翻译失败: " + e.getMessage();
        }
    }

    /**
     * 将中文翻译为英文
     * 
     * @param text 要翻译的中文文本
     * @return 翻译后的英文文本
     */
    public String translateToEnglish(String text) {
        return translate(text, LANG_CHINESE, LANG_ENGLISH);
    }

    /**
     * 将英文翻译为中文
     * 
     * @param text 要翻译的英文文本
     * @return 翻译后的中文文本
     */
    public String translateToChineseFromEnglish(String text) {
        return translate(text, LANG_ENGLISH, LANG_CHINESE);
    }

    /**
     * 发送请求到讯飞机器翻译（新）API
     * 
     * @param text     要翻译的文本
     * @param fromLang 源语言代码
     * @param toLang   目标语言代码
     * @return API响应
     * @throws Exception 请求异常
     */
    private String doRequest(String text, String fromLang, String toLang) throws Exception {
        URL realUrl = new URL(buildRequestUrl());
        URLConnection connection = realUrl.openConnection();
        HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
        httpURLConnection.setDoInput(true);
        httpURLConnection.setDoOutput(true);
        httpURLConnection.setRequestMethod("POST");
        httpURLConnection.setRequestProperty("Content-type", "application/json");

        OutputStream out = httpURLConnection.getOutputStream();
        String params = buildParam(text, fromLang, toLang);
        logger.debug("请求参数: {}", params.replaceAll(" ", ""));
        out.write(params.getBytes());
        out.flush();

        InputStream is = null;
        try {
            is = httpURLConnection.getInputStream();
        } catch (Exception e) {
            is = httpURLConnection.getErrorStream();
            throw new Exception("请求异常: " + "状态码 " + httpURLConnection.getResponseCode() +
                    " " + httpURLConnection.getResponseMessage() +
                    " " + readAllBytes(is));
        }
        return readAllBytes(is);
    }

    /**
     * 构建请求URL，包含鉴权
     * 
     * @return 构建好的请求URL
     */
    private String buildRequestUrl() {
        try {
            URL url = new URL(REQUEST_URL);
            // 获取当前日期并格式化
            SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
            format.setTimeZone(TimeZone.getTimeZone("GMT"));
            String date = format.format(new Date());
            String host = url.getHost();

            StringBuilder builder = new StringBuilder("host: ").append(host).append("\n")
                    .append("date: ").append(date).append("\n")
                    .append("POST ").append(url.getPath()).append(" HTTP/1.1");

            Charset charset = Charset.forName("UTF-8");
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec spec = new SecretKeySpec(API_SECRET.getBytes(charset), "HmacSHA256");
            mac.init(spec);
            byte[] hexDigits = mac.doFinal(builder.toString().getBytes(charset));
            String sha = Base64.getEncoder().encodeToString(hexDigits);

            String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"",
                    API_KEY, "hmac-sha256", "host date request-line", sha);
            String authBase = Base64.getEncoder().encodeToString(authorization.getBytes(charset));

            return String.format("%s?authorization=%s&host=%s&date=%s",
                    REQUEST_URL,
                    URLEncoder.encode(authBase, "UTF-8").replaceAll("\\+", "%20"),
                    URLEncoder.encode(host, "UTF-8"),
                    URLEncoder.encode(date, "UTF-8"));
        } catch (Exception e) {
            throw new RuntimeException("构建请求URL异常: " + e.getMessage());
        }
    }

    /**
     * 构建请求参数
     * 
     * @param text     要翻译的文本
     * @param fromLang 源语言代码
     * @param toLang   目标语言代码
     * @return 构建好的请求参数
     */
    private String buildParam(String text, String fromLang, String toLang) {
        // 对文本进行预处理，去除可能导致JSON格式错误的字符
        text = text.replace("\\", "\\\\")
                .replace("\"", "\\\"")
                .replace("\n", "\\n")
                .replace("\r", "\\r")
                .replace("\t", "\\t");

        // 资源ID参数处理
        String resIdParam = RES_ID.isEmpty() ? "" : "\"res_id\": \"" + RES_ID + "\",";

        // 构建请求JSON
        JSONObject requestJson = new JSONObject();

        // header部分
        JSONObject header = new JSONObject();
        header.put("app_id", APP_ID);
        header.put("status", 3);
        if (!RES_ID.isEmpty()) {
            header.put("res_id", RES_ID);
        }
        requestJson.put("header", header);

        // parameter部分
        JSONObject parameter = new JSONObject();
        JSONObject its = new JSONObject();
        its.put("from", fromLang);
        its.put("to", toLang);
        its.put("result", new JSONObject());
        parameter.put("its", its);
        requestJson.put("parameter", parameter);

        // payload部分
        JSONObject payload = new JSONObject();
        JSONObject inputData = new JSONObject();
        inputData.put("encoding", "utf8");
        inputData.put("status", 3);
        inputData.put("text", Base64.getEncoder().encodeToString(text.getBytes(StandardCharsets.UTF_8)));
        payload.put("input_data", inputData);
        requestJson.put("payload", payload);

        return requestJson.toJSONString();
    }

    /**
     * 读取流数据
     * 
     * @param is 输入流
     * @return 读取的字符串
     * @throws IOException IO异常
     */
    private String readAllBytes(InputStream is) throws IOException {
        byte[] b = new byte[1024];
        StringBuilder sb = new StringBuilder();
        int len = 0;
        while ((len = is.read(b)) != -1) {
            sb.append(new String(b, 0, len, "utf-8"));
        }
        return sb.toString();
    }
}